//
//  CCRObjects.m
//  iHealthEHR
//
//  Created by Joseph Ayo Akinyele on 3/15/10.
//  Copyright 2010 __MyCompanyName__. All rights reserved.
//

#import "CCRObject.h"


@implementation CCRObject
@synthesize editDate;
@synthesize item, description, ccrsection;
@synthesize XmlElement, plaintextXmlElement, encryptedXmlElement;

#define STAssertNotNil(a1, description, ...) \
do { \
@try {\
id a1value = (a1); \
if (a1value == nil) { \
NSString *_a1 = [NSString stringWithUTF8String:#a1]; \
NSString *_expression = [NSString stringWithFormat:@"((%@) != nil)", _a1]; \
[self failWithException:([NSException failureInCondition:_expression \
isTrue:NO \
inFile:[NSString stringWithUTF8String:__FILE__] \
atLine:__LINE__ \
withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \
} \
}\
@catch (id anException) {\
[self failWithException:([NSException failureInRaise:[NSString stringWithFormat:@"(%s) != nil fails", #a1] \
exception:anException \
inFile:[NSString stringWithUTF8String:__FILE__] \
atLine:__LINE__ \
withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \
}\
} while(0)


// Description: call object whenever you instantiate objects of this class
-(void) initOtherXMLObjects
{
	// see if XmlElement is encrypted
	BOOL result = [self isXMLEntryEncrypted];
	NSError *error = nil;
	if(result) {
		// save for when user decrypts. Should only be done once.
		if(encryptedXmlElement != nil)
			[encryptedXmlElement release];
		encryptedXmlElement = [[NSXMLElement alloc] initWithXMLString:[XmlElement XMLString] error:&error];
		// Note plaintextXML is set when user attempts to decrypt the entry.
	}
	else {
		// save for when user displays entry. Should only be set once.
		if(plaintextXmlElement != nil)
			[plaintextXmlElement release];
		plaintextXmlElement = [[NSXMLElement alloc] initWithXMLString:[XmlElement XMLString] error:&error];
	}	
}

// search through XmlElement for the 'EncryptedData' tag. If it exists, then return YES
// otherwise NO.
-(BOOL) isXMLEntryEncrypted
{
	// Assumes caller executed initOtherXMLObjects 
	if(XmlElement != nil) {
		NSArray *n = [XmlElement elementsForName:@"Body"];
		// NSLog(@"Checking for encrypted tags...");
		for(int i = 0; i < [n count]; i++) {
			// NSLog(@" Node ?=> %@", [[n objectAtIndex:i] name]);
			return [XMLParser searchForTag:[n objectAtIndex:i] withName:@"EncryptedData" orWith:@"[!ENCRYPTED ENTRY!]"];
		}
	}
	/* nil element */
	return NO;
}

+(BOOL) isThisEntryEncrypted:(NSXMLElement *) element
{
	// Assumes caller executed initOtherXMLObjects 
	if(element != nil) {
		NSArray *n = [element elementsForName:@"Body"];
		// NSLog(@"Checking for encrypted tags...");
		for(int i = 0; i < [n count]; i++) {
			// NSLog(@" Node ?=> %@", [[n objectAtIndex:i] name]);
			return [XMLParser searchForTag:[n objectAtIndex:i] withName:@"EncryptedData" orWith:@"[!ENCRYPTED ENTRY!]"];
		}
	}
	/* nil element */
	return NO;
}

-(BOOL) isEntryEncrypted
{
	/* if plain text set, then NO */
	if(plaintextXmlElement != nil) {
		return NO;
	}
	
	/* if encryptedXmlElement set, then YES */
	if(encryptedXmlElement != nil) {
		return YES;
	}	
	
	/* if neither set, then caller never sent the initOtherXMLObjects message */
	return NO;
}

/* This function makes sure that we have in the Encrypted tag => an ABE and an EncryptedData tag.
   If either is missing return NO!
 */
+(BOOL) isABEComplete:(NSXMLNode *) node
{
	NSEnumerator *e = [[node children] objectEnumerator];
	NSXMLNode *n;
	BOOL _abetag = NO, _aestag = NO;
	
	while (n = [e nextObject]) {
		if ([[n name] isEqualToString:@"ABE"] == YES) {
			_abetag = YES;
			NSLog(@"ABE tag => '%@'", [n name]);			
		}
		else if ([[n name] isEqualToString:@"EncryptedData"] == YES) {
			_aestag = YES;
			NSLog(@"AES tag => '%@'", [n name]);
		}		
	}

	if (_abetag == YES && _aestag == YES) {
		return YES;
	}
	
	return NO;
}

// Will take the plaintextXmlElement and encrypt under a specific ABE policy
-(void) encrypt
{
	return;
}

// will take the encryptedXmlElement and decrypt under a private-key.
// inputs = private-key or CPABE interface object
// output = transform the 'encryptedXmlElement' into 'plaintextXmlElement'
-(BOOL) decrypt:(CPABEInterface *) cpabe
{
	NSError *error = nil;
	// make sure private key has been downloaded.
	if(item != nil && XmlElement != nil) {		
		NSXMLNode *ciphertag = [self getEncryptedNode];
		if([CCRObject isABEComplete:ciphertag] == NO) {
			/* not encrypted : Return */
			NSLog(@"Element not ABE encrypted!");
			return NO;
		}
		NSLog(@"Decrypting => '%@' under some private-key.", [ciphertag name]);
		// NSLog(@"Ciphertext => '%@'", ciphertext);
		NSEnumerator *e = [[ciphertag children] objectEnumerator];
		NSXMLNode *n, *abenode, *aesnode;
		
		while (n = [e nextObject]) {
			if ([[n name] isEqualToString:@"ABE"] == YES) {
				abenode = n;
			}
			else if ([[n name] isEqualToString:@"EncryptedData"] == YES) {
				aesnode = n;
			}
		}		
	
		/* retrieve the base-64 ciphertext for abe and aes tags */
		NSString *abecipher64 = [abenode stringValue];
		NSString *aescipher64 = [aesnode stringValue];
		
		/* ABE decryption here */
		NSString *plaintext = [cpabe Decrypt:abecipher64 and:aescipher64];
		
		// NSLog(@"Plaintext => '%@'", plaintext);
		
		// test the plaintext XML to see if it is well-formed. How?
		NSError *error1 = nil;
		NSXMLDocument *testThis = [[NSXMLDocument alloc] initWithXMLString:plaintext options:0 error:&error1];
		if(error1 != nil) {
			[testThis release];
			[plaintext release];
			NSLog(@"Bad XML!!!! : %@", error1);
			return NO;
		}
		[testThis release];
		
		// transform 'cipher' into a 'plaintext' w/ ABE crypto methods...
		if(plaintextXmlElement != nil) {
			[plaintextXmlElement release];
		}
		
		plaintextXmlElement = [[NSXMLElement alloc] initWithXMLString:[encryptedXmlElement XMLString] error:&error];
		// NSString *plaintext = @"<DateTime><Type><Text>JAA Date Updated</Text></Type><ExactDateTime>2010-03-25T00:18:58Z</ExactDateTime></DateTime>";
		
		// use 'plain' to instantiate XMLElement
		NSXMLElement *plainXML = [[NSXMLElement alloc] initWithXMLString:plaintext error:&error];
		// deal with when we try uploading this CCR entry.
		if(bogusPlaintext != nil)
			[bogusPlaintext release];
		bogusPlaintext = [[NSXMLElement alloc] initWithXMLString:plaintext error:&error];
		
		[XMLParser findAndReplace:plaintextXmlElement withName:@"Encrypted" toThis:plainXML];
		// NSLog(@"decrypted XmlElement = '%@'", [plaintextXmlElement XMLString]);
		
		[plaintext release];
		[plainXML release];

		return YES;
	}
	return NO;
}

/*
+(NSString *) targetInCCRFor:(NSString *) parent
{
	if([parent isEqualToString:@"Medications"]) {
		return @"Medication";
	}
	
	return nil;
}*/

+(NSString *) getbogusXML:(NSString *) parent
{
	// XML for Medication CCR type (GOOD)
	if([parent isEqualToString:@"Medications"]) {
		return @"<Medication><Source></Source><CCRDataObjectID>oePzBrHceTU-0</CCRDataObjectID><Status>"
		"<Text>ACTIVE</Text></Status><Product><ProductName><Text>[!ENCRYPTED ENTRY!]</Text>"
		"<Code><Value>9999</Value><CodingSystem>Google</CodingSystem></Code></ProductName>"
		"</Product><Directions><Direction><Route><Text>[!ENCRYPTED ENTRY!]</Text>"
		"<Code><Value>9999</Value><CodingSystem>Google</CodingSystem></Code>"
		"<RouteSequencePosition>0</RouteSequencePosition></Route></Direction></Directions>"
		"</Medication>";		
	}
	// XML for Condition CCR type (GOOD)
	else if([parent isEqualToString:@"Problems"]) {
		return @"<Problem><Source></Source><CCRDataObjectID>BB0005</CCRDataObjectID><DateTime><Type><Text>Date Updated</Text>"
		"</Type><ExactDateTime>2010-03-25T00:18:58Z</ExactDateTime></DateTime><Type><Text>Problem</Text></Type>"
		"<Description><Text>[!ENCRYPTED ENTRY!]</Text></Description>"
		"</Problem>";
	}
	// XML for Allergies CCR type (?)
	else if([parent isEqualToString:@"Alerts"]) {
		return @"<Alert><Source></Source><CCRDataObjectID>BWzVHWFgWtc-0</CCRDataObjectID><Type><Text>[!ENCRYPTED ENTRY!]</Text></Type><Description>"
		"<Text>[!ENCRYPTED ENTRY!]</Text><Code><Value>9999</Value><CodingSystem>Google</CodingSystem></Code><Code><Value>9999</Value>"
		"<CodingSystem>Google</CodingSystem></Code></Description><Status><Text>ACTIVE</Text></Status></Alert>";		
	}
	// 
	else if([parent isEqualToString:@"Procedures"]) {
		return @"<Procedure><Source></Source><CCRDataObjectID>Egpr_Rh9LPo-0</CCRDataObjectID><Description>"
		"<Text>[!ENCRYPTED ENTRY!]</Text>"
		"<Code><Value>9999</Value><CodingSystem>Google</CodingSystem></Code><Code><Value>9999</Value>"
		"<CodingSystem>Google</CodingSystem></Code></Description>"
		"</Procedure>";
	}
	else if([parent isEqualToString:@"Results"]) {
		return @"<Result><Source></Source><CCRDataObjectID>qkfOJxQmokw-1</CCRDataObjectID>"
		"<Test><CCRDataObjectID>qkfOJxQmokw-0</CCRDataObjectID><DateTime><Type>"
		"<Text>Collection start date</Text></Type><ExactDateTime>1999-09-09</ExactDateTime>"
		"</DateTime><Description><Text>[!ENCRYPTED ENTRY!]</Text><Code><Value>9999</Value>"
		"<CodingSystem>Google</CodingSystem></Code>"
		"</Description></Test></Result>";
	}
	else if([parent isEqualToString:@"Immunizations"]) {
		return @"<Immunization><Source></Source><CCRDataObjectID>BB0021</CCRDataObjectID><Type><Text>[!ENCRYPTED ENTRY!]</Text></Type>"
		"<Product><ProductName><Text>[!ENCRYPTED ENTRY!]</Text><Code><Value>9999</Value><CodingSystem>Google</CodingSystem>"
		"<Version>9999</Version></Code></ProductName></Product></Immunization>";
	}
	return nil;
}

-(BOOL) decryptElementFromGoogleHealth:(CPABEInterface *) cpabe
{
	NSError *error = nil;
	if(encryptedXmlElement == nil) {
		return NO;
	}
	NSLog(@"DEBUG: Print encryptedXmlElement: '%@'\n", encryptedXmlElement);
	// get the source tags from the XML elelement
	NSXMLNode *actor = [self getEncryptedSource];	
	if(actor == nil) {
		NSLog(@"Entry does not contain encrypted data.");
		return NO;
	}
	// get elements of plaintext
	if (plaintextXmlElement != nil)
		[plaintextXmlElement release];
	plaintextXmlElement = [[NSXMLElement alloc] initWithXMLString:[encryptedXmlElement XMLString] error:&error];
	
	NSArray *b = [plaintextXmlElement elementsForName:@"Body"];
	NSXMLNode *plainBody = [[b objectAtIndex:0] childAtIndex:0];
	
	// parse the ABE data, decrypt and reconstruct the XML
	NSString *abedata = nil;
	NSEnumerator *e = [[actor children] objectEnumerator];
	NSXMLNode *actorRole;
	while(actorRole = [e nextObject]) {
		if([[actorRole name] isEqualToString:@"ActorRole"]) {
			NSString *blob64 = [actorRole stringValue];
			// NSLog(@"Blob-64 => '%@'", blob64);
			abedata = [CCRObject base64Decode:blob64];
			break;
		}
	}
	
	// something went wrong
	if(abedata == nil) {
		return NO;
	}
	
	// deconstruct the ABE data tag
	NSXMLElement *encryptedData = [[NSXMLElement alloc] initWithXMLString:abedata error:&error];
	NSXMLNode *s = [encryptedData attributeForName:@"Parent"];
	NSString *parent = [s stringValue];
	NSLog(@" DEBUG: Add encrypted data to => '%@' node", parent);			
	
	// parse the abe ciphertext and abe ciphertext
	NSXMLNode *encrypted = [[encryptedData elementsForName:@"Encrypted"] objectAtIndex:0];
	e = [[encrypted children] objectEnumerator];
	NSXMLNode *n, *abenode, *aesnode;
	
	while (n = [e nextObject]) {
		if ([[n name] isEqualToString:@"ABE"] == YES) {
			abenode = n;
		}
		else if ([[n name] isEqualToString:@"EncryptedData"] == YES) {
			aesnode = n;
		}
	}
#ifdef HEALTH_DEBUG		
	NSLog(@"DEBUG: abenode => '%@'", [abenode stringValue]);
	NSLog(@"DEBUG: aesnode => '%@'", [aesnode stringValue]);
#endif
	
	/* ABE decryption here */
	NSString *plaintext = [cpabe Decrypt:[abenode stringValue] and:[aesnode stringValue]];
	
	// test the plaintext XML to see if it is well-formed. How?
	NSError *error1 = nil;
	NSXMLDocument *testThis = [[NSXMLDocument alloc] initWithXMLString:plaintext options:0 error:&error1];
	if(error1 != nil) {
		[testThis release];
		[plaintext release];
		NSLog(@"Bad XML!!!! : %@", error1);
		return NO;
	}
	[testThis release];
	
	
	NSLog(@"Plaintext => '%@'", plaintext);
	// create XML element for authentic plaintext
	NSXMLElement *authXML = [[NSXMLElement alloc] initWithXMLString:plaintext error:&error];
	
	// reconstruct the original CCR now...
	NSLog(@"plainBody => '%@', target parent '%@'", [plainBody name], parent);
	if([[plainBody name] isEqualToString:parent]) {
		// remove bogus XML child
		NSXMLNode *child = [plainBody childAtIndex:0];
		NSXMLElement *p = (NSXMLElement *) plainBody;
		[p removeChild:child];
		// add original authentic XML
		[p addChild:authXML];
	}
	
	NSLog(@"Original? => '%@'", plaintextXmlElement);
	
	[plaintext release];
	[encryptedData release];
	[abedata release];
	return YES;
}

/*-(NSString *) retrieveABEpolicy
{
	
} */

// Takes encrypted XML Element and base64 encodes it and stores under 
// Source tag. Places an identifier inside the <ActorID> tag and the ciphertext
// is stored under <ActorRole>. The identifier describes the PARENT tag in which the Encrypted element
// was extracted.
-(NSXMLElement *) transformEncryptedForGoogleHealth:(CPABEInterface *) cpabe 
{
	if(encryptedXmlElement == nil) {
		/* entry does nto contain encrypted data elements */
		return nil;
	}
	
	NSXMLElement *encryptedData = [XMLParser findAndReturnParent:encryptedXmlElement withName:@"Encrypted"];
	// NSLog(@" DEBUG: EncryptedData => '%@'", [encryptedData XMLString]);
	
	if(encryptedData == nil || [encryptedData childCount] == 0) {
		NSLog(@"Error: could not find any encrypted data tags.");
		return nil;
	}
	NSError *error = nil;
	NSXMLElement *uploadXML = [[NSXMLElement alloc] initWithXMLString:[encryptedXmlElement XMLString] error:&error];
	// base-64 encode
	NSString *base64Encoded = [CCRObject base64Encode:[encryptedData XMLString]];	
	NSString *actor;
	NSXMLElement *xml;
	
/*	NSEnumerator *e = [[[encryptedData childAtIndex:0] children] objectEnumerator];
	NSXMLNode *n, *abenode, *aesnode;
	
	while (n = [e nextObject]) {
		if ([[n name] isEqualToString:@"ABE"] == YES) {
			abenode = n;
		}
		else if ([[n name] isEqualToString:@"EncryptedData"] == YES) {
			aesnode = n;
		}
	}
*/
	// add bogus information
	// add encrypted data into tags
	NSXMLNode *s = [encryptedData attributeForName:@"Parent"];
	NSString *parent = [s stringValue];
	NSLog(@" DEBUG: Add source tag to => '%@' node", parent);		
	NSString *plaintext = [CCRObject getbogusXML:parent];
	// NSLog(@"Plaintext => '%@'", plaintext);			
	bogusPlaintext = [[NSXMLElement alloc] initWithXMLString:plaintext error:&error];
	[plaintext release];
	
	[XMLParser findAndReplace:uploadXML withName:@"Encrypted" toThis:bogusPlaintext];	
	
	// store encoded xml in source tag of uploadXML element
	if([XMLParser searchForTag:uploadXML withName:@"Source" orWith:@""] == YES) {
		// create actor tags for it.
		actor = [[NSString alloc] initWithFormat:@"<Actor><ActorID>[!ENCRYPTED ENTRY!]</ActorID><ActorRole><Text>%@</Text></ActorRole></Actor>", base64Encoded];
		xml = [[NSXMLElement alloc] initWithXMLString:actor error:&error];
		[XMLParser AddChildToNode:uploadXML withName:@"Source" withThis:xml]; 
	}
	
	NSLog(@"Uploaded XML => '%@'", uploadXML);
	
	/* free all memory here */
	// [uploadXML release];
	[encryptedData release];
	[actor release];
	[xml release];
	// Note: encryptedData is autoreleased, no need to free here
	// [CCRObject base64Decode:base64Encoded];
	return uploadXML;
}

/* Pulls the ABE policy from the ciphertext for display purposes: */
/* May consider transforming policy string into "dot" notation in XML? -- for now display string. */
-(NSString *) getABEPolicy:(CPABEInterface *) cpabe with:(BOOL) isGoogle
{
	if(encryptedXmlElement == nil) {
		/* entry does nto contain encrypted data elements */
		return nil;
	}

	NSString *abecipher64, *policy;
	NSXMLNode *n, *abenode;
	NSEnumerator *e;
	NSError *error;
	
	if(isGoogle) {
		// pull the encryptedData from source tags?
		NSXMLNode *actor = [self getEncryptedSource];
		if(actor == nil) {
			NSLog(@"Actor NULL, cant find encrypted data?");
			return nil;
		}
		// parse the ABE data, decrypt and reconstruct the XML
		NSString *abedata = nil;
		e = [[actor children] objectEnumerator];
		NSXMLNode *actorRole;
		while(actorRole = [e nextObject]) {
			if([[actorRole name] isEqualToString:@"ActorRole"]) {
				NSString *blob64 = [actorRole stringValue];
				//NSLog(@"DEBUG: Blob-64 => '%@'", blob64);
				abedata = [CCRObject base64Decode:blob64];
				break;
			}
		}
		//NSLog(@"DEBUG: abedata => '%@'", abedata);
		NSXMLElement *encryptedData = [[NSXMLElement alloc] initWithXMLString:abedata error:&error];
		NSXMLNode *encrypted = [[encryptedData elementsForName:@"Encrypted"] objectAtIndex:0];
	
		e = [[encrypted children] objectEnumerator];
		while(n = [e nextObject]) {
			if ([[n name] isEqualToString:@"ABE"] == YES) {
				abenode = n;
				break;
			}			
		}	
		
		// common code...
		[encryptedData release];
	}
	else {
		/* pull encrypted data tag from regular place */
		NSXMLNode *ciphertag = [self getEncryptedNode];
		if([CCRObject isABEComplete:ciphertag] == NO) {
			/* not encrypted : Return */
			NSLog(@"Element not ABE encrypted!");
			return NO;
		}
		NSLog(@"Deciphering '%@'", [ciphertag name]);
		// NSLog(@"Ciphertext => '%@'", ciphertext);
		e = [[ciphertag children] objectEnumerator];		
		while (n = [e nextObject]) {
			if ([[n name] isEqualToString:@"ABE"] == YES) {
				abenode = n;
				break;
			}
		}		
		
		// common code...
	}
	
	if(abenode == nil) {
		return nil;
	}
	
	/* retrieve the base-64 ciphertext for abe and aes tags */
	abecipher64 = [abenode stringValue];
//	NSLog(@"ABE blob => '%@'", abecipher64);
	policy = [cpabe ReturnPolicy:abecipher64];
	
	NSLog(@"Result => '%@'", policy);
	/* caller must free */
	return policy;		
}

/* Simply returns the encryptedData and ABE tags and values */
-(NSXMLNode *) getEncryptedNode
{
	BOOL _found = NO;
	// NSString *ciphertext;
	NSXMLNode *ciphertext;
	NSArray *n = [encryptedXmlElement elementsForName:@"Body"];
	for(int i = 0; i < [n count]; i++) {
		NSArray *e = [XMLParser findChild:[n objectAtIndex:i] withTag:@"Encrypted"];
		if([e count] > 0) {
			_found = YES;
			// ciphertext =  [[e objectAtIndex:0] stringValue];
			ciphertext = [e objectAtIndex:0];
		}
	}
	
	if(_found) {
		return ciphertext;
	}
	return nil;
}

/* Retrieve 'Source' tag from the Xml element */
-(NSXMLNode *) getEncryptedSource
{
	BOOL _found = NO;
	NSXMLNode *s,*source;
	NSEnumerator *e1;
	NSArray *n = [encryptedXmlElement elementsForName:@"Body"];
	if ([n count] == 0) {
		return nil;
	}	
	NSArray *e = [XMLParser findChild:[n objectAtIndex:0] withTag:@"Source"];
	if([e count] > 0) {
	  for(int k = 0; k < [e count]; k++) {
		// printf("e ptr = '%i'\n", k);  
		e1 = [[[e objectAtIndex:k] children] objectEnumerator];		
		while(s = [e1 nextObject]) {
			if([[s name] isEqualToString:@"Actor"]) {
				// see if the ActorID == '[!ENCRYPTED ENTRY!]'
				for(int i = 0; i < [s childCount]; i++) {
					NSXMLNode *tmp = [s childAtIndex:i];
					if([[tmp name] isEqualToString:@"ActorID"]) {
						if([[tmp stringValue] isEqualToString:@"[!ENCRYPTED ENTRY!]"]) {
							// we found our encrypted data tag
							// NSLog(@"Found encrypted entry tag");
							_found = YES;
							source = s;
							break;
						}
					}
				}
			}
		} // end while
	  } // end for
	}
		
	if(_found) {
		return source;
	}
	return nil;
}

-(NSXMLElement *) getPlainText
{
	// if not nil, then it is already set?
	if(plaintextXmlElement != nil)
		return plaintextXmlElement;
	
	if(XmlElement != nil) 
		return XmlElement;
	
	return nil;
}

-(void) printObject
{
	NSLog(@"<--------------------------->");
	NSLog(@"name: '%@'", self.item);
	NSLog(@"section: '%@'", self.ccrsection);
	NSLog(@"edit date: '%@'", self.editDate);
	if(plaintextXmlElement != nil)
		NSLog(@"Plaintext: '%@'\n", [plaintextXmlElement XMLString]);
	if(encryptedXmlElement != nil)
		NSLog(@"Encrypted: '%@'\n", [encryptedXmlElement XMLString]);	
	NSLog(@"<--------------------------->");
}

+(NSString *) base64Encode:(NSString *) input
{
	NSData *data = [input dataUsingEncoding: NSASCIIStringEncoding];
	
	//NSLog(@"Input => '%@'", input);
	//NSLog(@"Base 64 Encoded => '%@'", [data base64EncodedString]);
	NSString *result = [data base64EncodedString];
	// [data release];
	return result;
}

+(NSString *) base64Decode:(NSString *) input
{
	NSData *data = [NSData dataFromBase64String:input];
	NSString *str = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
	
	//NSLog(@"Input => '%@'", input);
	//NSLog(@"Base 64 Decoded => '%@'", str);
		
	// [str release];
	return str;
}

+(void) popUpNotice:(NSString *) mytitle withMessage:(NSString *) message
{
	if(message == nil || mytitle == nil) {
		return;
	}
	
	UIAlertView *status = [[UIAlertView alloc] initWithTitle:mytitle message:message
													delegate:self cancelButtonTitle:nil 
											otherButtonTitles:@"OK", nil];
	[status show];
	[status release];	
	return;
}


- (void)dealloc {
  [bogusPlaintext release];
  [XmlElement release];
  [encryptedXmlElement release];
  [plaintextXmlElement release];
  [super dealloc];
}  

@end
